home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / security / socks / rftp / glob.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-21  |  11.3 KB  |  688 lines

  1. /*
  2.  * Copyright (c) 1980 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)glob.c    5.9 (Berkeley) 2/25/91";
  36. #endif /* not lint */
  37.  
  38. /*
  39.  * C-shell glob for random programs.
  40.  */
  41.  
  42. #include <sys/param.h>
  43. #include <sys/stat.h>
  44. #ifdef COMPAT
  45. #include <sys/dir.h>
  46. #include <sys/dirent.h>
  47. #else
  48. #include <dirent.h>
  49. #endif
  50.  
  51. #include <pwd.h>
  52. #include <errno.h>
  53. #include <stdio.h>
  54. #ifndef COMPAT
  55. #include <stdlib.h>
  56. #endif
  57. #include <string.h>
  58.  
  59. #define    QUOTE 0200
  60. #define    TRIM 0177
  61. #define    eq(a,b)        (strcmp(a, b)==0)
  62. #define    GAVSIZ        (NCARGS/6)
  63. #define    isdir(d)    ((d.st_mode & S_IFMT) == S_IFDIR)
  64.  
  65. static    char **gargv;        /* Pointer to the (stack) arglist */
  66. static    int gargc;        /* Number args in gargv */
  67. static    int gnleft;
  68. static    short gflag;
  69. static    int tglob();
  70. char    **ftpglob();
  71. char    *globerr;
  72. char    *home;
  73. extern    int errno;
  74. static    char *strspl(), *strend();
  75. char    **copyblk();
  76.  
  77. static void acollect(), addpath(), collect(), expand(), Gcat();
  78. static void ginit(), matchdir(), rscan(), sort();
  79. static int amatch(), execbrc(), match();
  80.  
  81. static    int globcnt;
  82.  
  83. char    *globchars = "`{[*?";
  84.  
  85. static    char *gpath, *gpathp, *lastgpathp;
  86. static    int globbed;
  87. static    char *entp;
  88. static    char **sortbas;
  89.  
  90. char **
  91. ftpglob(v)
  92.     register char *v;
  93. {
  94.     char agpath[BUFSIZ];
  95.     char *agargv[GAVSIZ];
  96.     char *vv[2];
  97.     vv[0] = v;
  98.     vv[1] = 0;
  99.     gflag = 0;
  100.     rscan(vv, tglob);
  101.     if (gflag == 0)
  102.         return (copyblk(vv));
  103.  
  104.     globerr = 0;
  105.     gpath = agpath; gpathp = gpath; *gpathp = 0;
  106.     lastgpathp = &gpath[sizeof agpath - 2];
  107.     ginit(agargv); globcnt = 0;
  108.     collect(v);
  109.     if (globcnt == 0 && (gflag&1)) {
  110.         blkfree(gargv), gargv = 0;
  111.         return (0);
  112.     } else
  113.         return (gargv = copyblk(gargv));
  114. }
  115.  
  116. static void
  117. ginit(agargv)
  118.     char **agargv;
  119. {
  120.  
  121.     agargv[0] = 0; gargv = agargv; sortbas = agargv; gargc = 0;
  122.     gnleft = NCARGS - 4;
  123. }
  124.  
  125. static void
  126. collect(as)
  127.     register char *as;
  128. {
  129.     if (eq(as, "{") || eq(as, "{}")) {
  130.         Gcat(as, "");
  131.         sort();
  132.     } else
  133.         acollect(as);
  134. }
  135.  
  136. static void
  137. acollect(as)
  138.     register char *as;
  139. {
  140.     register int ogargc = gargc;
  141.  
  142.     gpathp = gpath; *gpathp = 0; globbed = 0;
  143.     expand(as);
  144.     if (gargc != ogargc)
  145.         sort();
  146. }
  147.  
  148. static void
  149. sort()
  150. {
  151.     register char **p1, **p2, *c;
  152.     char **Gvp = &gargv[gargc];
  153.  
  154.     p1 = sortbas;
  155.     while (p1 < Gvp-1) {
  156.         p2 = p1;
  157.         while (++p2 < Gvp)
  158.             if (strcmp(*p1, *p2) > 0)
  159.                 c = *p1, *p1 = *p2, *p2 = c;
  160.         p1++;
  161.     }
  162.     sortbas = Gvp;
  163. }
  164.  
  165. static void
  166. expand(as)
  167.     char *as;
  168. {
  169.     register char *cs;
  170.     register char *sgpathp, *oldcs;
  171.     struct stat stb;
  172.  
  173.     sgpathp = gpathp;
  174.     cs = as;
  175.     if (*cs == '~' && gpathp == gpath) {
  176.         addpath('~');
  177.         for (cs++; letter(*cs) || digit(*cs) || *cs == '-';)
  178.             addpath(*cs++);
  179.         if (!*cs || *cs == '/') {
  180.             if (gpathp != gpath + 1) {
  181.                 *gpathp = 0;
  182.                 if (gethdir(gpath + 1))
  183.                     globerr = "Unknown user name after ~";
  184.                 (void) strcpy(gpath, gpath + 1);
  185.             } else
  186.                 (void) strcpy(gpath, home);
  187.             gpathp = strend(gpath);
  188.         }
  189.     }
  190.     while (!any(*cs, globchars)) {
  191.         if (*cs == 0) {
  192.             if (!globbed)
  193.                 Gcat(gpath, "");
  194.             else if (stat(gpath, &stb) >= 0) {
  195.                 Gcat(gpath, "");
  196.                 globcnt++;
  197.             }
  198.             goto endit;
  199.         }
  200.         addpath(*cs++);
  201.     }
  202.     oldcs = cs;
  203.     while (cs > as && *cs != '/')
  204.         cs--, gpathp--;
  205.     if (*cs == '/')
  206.         cs++, gpathp++;
  207.     *gpathp = 0;
  208.     if (*oldcs == '{') {
  209.         (void) execbrc(cs, ((char *)0));
  210.         return;
  211.     }
  212.     matchdir(cs);
  213. endit:
  214.     gpathp = sgpathp;
  215.     *gpathp = 0;
  216. }
  217.  
  218. static void
  219. matchdir(pattern)
  220.     char *pattern;
  221. {
  222.     struct stat stb;
  223.     register struct dirent *dp;
  224.     DIR *dirp;
  225.  
  226.     dirp = opendir(gpath);
  227.     if (dirp == NULL) {
  228.         if (globbed)
  229.             return;
  230.         goto patherr2;
  231.     }
  232.     if (fstat(dirp->dd_fd, &stb) < 0)
  233.         goto patherr1;
  234.     if (!isdir(stb)) {
  235.         errno = ENOTDIR;
  236.         goto patherr1;
  237.     }
  238.     while ((dp = readdir(dirp)) != NULL) {
  239.         if (dp->d_ino == 0)
  240.             continue;
  241.         if (match(dp->d_name, pattern)) {
  242.             Gcat(gpath, dp->d_name);
  243.             globcnt++;
  244.         }
  245.     }
  246.     closedir(dirp);
  247.     return;
  248.  
  249. patherr1:
  250.     closedir(dirp);
  251. patherr2:
  252.     globerr = "Bad directory components";
  253. }
  254.  
  255. static int
  256. execbrc(p, s)
  257.     char *p, *s;
  258. {
  259.     char restbuf[BUFSIZ + 2];
  260.     register char *pe, *pm, *pl;
  261.     int brclev = 0;
  262.     char *lm, savec, *sgpathp;
  263.  
  264.     for (lm = restbuf; *p != '{'; *lm++ = *p++)
  265.         continue;
  266.     for (pe = ++p; *pe; pe++)
  267.     switch (*pe) {
  268.  
  269.     case '{':
  270.         brclev++;
  271.         continue;
  272.  
  273.     case '}':
  274.         if (brclev == 0)
  275.             goto pend;
  276.         brclev--;
  277.         continue;
  278.  
  279.     case '[':
  280.         for (pe++; *pe && *pe != ']'; pe++)
  281.             continue;
  282.         continue;
  283.     }
  284. pend:
  285.     brclev = 0;
  286.     for (pl = pm = p; pm <= pe; pm++)
  287.     switch (*pm & (QUOTE|TRIM)) {
  288.  
  289.     case '{':
  290.         brclev++;
  291.         continue;
  292.  
  293.     case '}':
  294.         if (brclev) {
  295.             brclev--;
  296.             continue;
  297.         }
  298.         goto doit;
  299.  
  300.     case ','|QUOTE:
  301.     case ',':
  302.         if (brclev)
  303.             continue;
  304. doit:
  305.         savec = *pm;
  306.         *pm = 0;
  307.         (void) strcpy(lm, pl);
  308.         (void) strcat(restbuf, pe + 1);
  309.         *pm = savec;
  310.         if (s == 0) {
  311.             sgpathp = gpathp;
  312.             expand(restbuf);
  313.             gpathp = sgpathp;
  314.             *gpathp = 0;
  315.         } else if (amatch(s, restbuf))
  316.             return (1);
  317.         sort();
  318.         pl = pm + 1;
  319.         if (brclev)
  320.             return (0);
  321.         continue;
  322.  
  323.     case '[':
  324.         for (pm++; *pm && *pm != ']'; pm++)
  325.             continue;
  326.         if (!*pm)
  327.             pm--;
  328.         continue;
  329.     }
  330.     if (brclev)
  331.         goto doit;
  332.     return (0);
  333. }
  334.  
  335. static int
  336. match(s, p)
  337.     char *s, *p;
  338. {
  339.     register int c;
  340.     register char *sentp;
  341.     char sglobbed = globbed;
  342.  
  343.     if (*s == '.' && *p != '.')
  344.         return (0);
  345.     sentp = entp;
  346.     entp = s;
  347.     c = amatch(s, p);
  348.     entp = sentp;
  349.     globbed = sglobbed;
  350.     return (c);
  351. }
  352.  
  353. static int
  354. amatch(s, p)
  355.     register char *s, *p;
  356. {
  357.     register int scc;
  358.     int ok, lc;
  359.     char *sgpathp;
  360.     struct stat stb;
  361.     int c, cc;
  362.  
  363.     globbed = 1;
  364.     for (;;) {
  365.         scc = *s++ & TRIM;
  366.         switch (c = *p++) {
  367.  
  368.         case '{':
  369.             return (execbrc(p - 1, s - 1));
  370.  
  371.         case '[':
  372.             ok = 0;
  373.             lc = 077777;
  374.             while (cc = *p++) {
  375.                 if (cc == ']') {
  376.                     if (ok)
  377.                         break;
  378.                     return (0);
  379.                 }
  380.                 if (cc == '-') {
  381.                     if (lc <= scc && scc <= *p++)
  382.                         ok++;
  383.                 } else
  384.                     if (scc == (lc = cc))
  385.                         ok++;
  386.             }
  387.             if (cc == 0)
  388.                 if (ok)
  389.                     p--;
  390.                 else
  391.                     return 0;
  392.             continue;
  393.  
  394.         case '*':
  395.             if (!*p)
  396.                 return (1);
  397.             if (*p == '/') {
  398.                 p++;
  399.                 goto slash;
  400.             }
  401.             s--;
  402.             do {
  403.                 if (amatch(s, p))
  404.                     return (1);
  405.             } while (*s++);
  406.             return (0);
  407.  
  408.         case 0:
  409.             return (scc == 0);
  410.  
  411.         default:
  412.             if (c != scc)
  413.                 return (0);
  414.             continue;
  415.  
  416.         case '?':
  417.             if (scc == 0)
  418.                 return (0);
  419.             continue;
  420.  
  421.         case '/':
  422.             if (scc)
  423.                 return (0);
  424. slash:
  425.             s = entp;
  426.             sgpathp = gpathp;
  427.             while (*s)
  428.                 addpath(*s++);
  429.             addpath('/');
  430.             if (stat(gpath, &stb) == 0 && isdir(stb))
  431.                 if (*p == 0) {
  432.                     Gcat(gpath, "");
  433.                     globcnt++;
  434.                 } else
  435.                     expand(p);
  436.             gpathp = sgpathp;
  437.             *gpathp = 0;
  438.             return (0);
  439.         }
  440.     }
  441. }
  442.  
  443. static
  444. Gmatch(s, p)
  445.     register char *s, *p;
  446. {
  447.     register int scc;
  448.     int ok, lc;
  449.     int c, cc;
  450.  
  451.     for (;;) {
  452.         scc = *s++ & TRIM;
  453.         switch (c = *p++) {
  454.  
  455.         case '[':
  456.             ok = 0;
  457.             lc = 077777;
  458.             while (cc = *p++) {
  459.                 if (cc == ']') {
  460.                     if (ok)
  461.                         break;
  462.                     return (0);
  463.                 }
  464.                 if (cc == '-') {
  465.                     if (lc <= scc && scc <= *p++)
  466.                         ok++;
  467.                 } else
  468.                     if (scc == (lc = cc))
  469.                         ok++;
  470.             }
  471.             if (cc == 0)
  472.                 if (ok)
  473.                     p--;
  474.                 else
  475.                     return 0;
  476.             continue;
  477.  
  478.         case '*':
  479.             if (!*p)
  480.                 return (1);
  481.             for (s--; *s; s++)
  482.                 if (Gmatch(s, p))
  483.                     return (1);
  484.             return (0);
  485.  
  486.         case 0:
  487.             return (scc == 0);
  488.  
  489.         default:
  490.             if ((c & TRIM) != scc)
  491.                 return (0);
  492.             continue;
  493.  
  494.         case '?':
  495.             if (scc == 0)
  496.                 return (0);
  497.             continue;
  498.  
  499.         }
  500.     }
  501. }
  502.  
  503. static void
  504. Gcat(s1, s2)
  505.     register char *s1, *s2;
  506. {
  507.     register int len = strlen(s1) + strlen(s2) + 1;
  508.  
  509.     if (len >= gnleft || gargc >= GAVSIZ - 1)
  510.         globerr = "Arguments too long";
  511.     else {
  512.         gargc++;
  513.         gnleft -= len;
  514.         gargv[gargc] = 0;
  515.         gargv[gargc - 1] = strspl(s1, s2);
  516.     }
  517. }
  518.  
  519. static void
  520. addpath(c)
  521.     char c;
  522. {
  523.  
  524.     if (gpathp >= lastgpathp)
  525.         globerr = "Pathname too long";
  526.     else {
  527.         *gpathp++ = c;
  528.         *gpathp = 0;
  529.     }
  530. }
  531.  
  532. static void
  533. rscan(t, f)
  534.     register char **t;
  535.     int (*f)();
  536. {
  537.     register char *p, c;
  538.  
  539.     while (p = *t++) {
  540.         if (f == tglob)
  541.             if (*p == '~')
  542.                 gflag |= 2;
  543.             else if (eq(p, "{") || eq(p, "{}"))
  544.                 continue;
  545.         while (c = *p++)
  546.             (*f)(c);
  547.     }
  548. }
  549. /*
  550. static
  551. scan(t, f)
  552.     register char **t;
  553.     int (*f)();
  554. {
  555.     register char *p, c;
  556.  
  557.     while (p = *t++)
  558.         while (c = *p)
  559.             *p++ = (*f)(c);
  560. } */
  561.  
  562. static
  563. tglob(c)
  564.     register char c;
  565. {
  566.  
  567.     if (any(c, globchars))
  568.         gflag |= c == '{' ? 2 : 1;
  569.     return (c);
  570. }
  571. /*
  572. static
  573. trim(c)
  574.     char c;
  575. {
  576.  
  577.     return (c & TRIM);
  578. } */
  579.  
  580.  
  581. letter(c)
  582.     register char c;
  583. {
  584.  
  585.     return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '_');
  586. }
  587.  
  588. digit(c)
  589.     register char c;
  590. {
  591.  
  592.     return (c >= '0' && c <= '9');
  593. }
  594.  
  595. any(c, s)
  596.     register int c;
  597.     register char *s;
  598. {
  599.  
  600.     while (*s)
  601.         if (*s++ == c)
  602.             return(1);
  603.     return(0);
  604. }
  605. blklen(av)
  606.     register char **av;
  607. {
  608.     register int i = 0;
  609.  
  610.     while (*av++)
  611.         i++;
  612.     return (i);
  613. }
  614.  
  615. char **
  616. blkcpy(oav, bv)
  617.     char **oav;
  618.     register char **bv;
  619. {
  620.     register char **av = oav;
  621.  
  622.     while (*av++ = *bv++)
  623.         continue;
  624.     return (oav);
  625. }
  626.  
  627. blkfree(av0)
  628.     char **av0;
  629. {
  630.     register char **av = av0;
  631.  
  632.     while (*av)
  633.         free(*av++);
  634. }
  635.  
  636. static
  637. char *
  638. strspl(cp, dp)
  639.     register char *cp, *dp;
  640. {
  641.     register char *ep = malloc((unsigned)(strlen(cp) + strlen(dp) + 1));
  642.  
  643.     if (ep == (char *)0)
  644.         fatal("Out of memory");
  645.     (void) strcpy(ep, cp);
  646.     (void) strcat(ep, dp);
  647.     return (ep);
  648. }
  649.  
  650. char **
  651. copyblk(v)
  652.     register char **v;
  653. {
  654.     register char **nv = (char **)malloc((unsigned)((blklen(v) + 1) *
  655.                         sizeof(char **)));
  656.     if (nv == (char **)0)
  657.         fatal("Out of memory");
  658.  
  659.     return (blkcpy(nv, v));
  660. }
  661.  
  662. static
  663. char *
  664. strend(cp)
  665.     register char *cp;
  666. {
  667.  
  668.     while (*cp)
  669.         cp++;
  670.     return (cp);
  671. }
  672. /*
  673.  * Extract a home directory from the password file
  674.  * The argument points to a buffer where the name of the
  675.  * user whose home directory is sought is currently.
  676.  * We write the home directory of the user back there.
  677.  */
  678. gethdir(home)
  679.     char *home;
  680. {
  681.     register struct passwd *pp = getpwnam(home);
  682.  
  683.     if (!pp || home + strlen(pp->pw_dir) >= lastgpathp)
  684.         return (1);
  685.     (void) strcpy(home, pp->pw_dir);
  686.     return (0);
  687. }
  688.